package com.thiswhyme.demo.msgpush.core.impl.nio;

import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description: channel管理器
 * @author: thiswhyme
 * @date: 2021/9/29
 */
@Slf4j
public class ChannelManager {

    private ChannelManager() {}

    /**
     * Channel组，管理所有的Channel
     */
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 用户连接Channel池
     */
    private static ConcurrentHashMap<String, Channel> userChannelMap = new ConcurrentHashMap<>();

    /**
     * 获取所有用户Channel
     * @return
     */
    public static Map<String, Channel> getUserChannelMap() {
        return userChannelMap;
    }

    /**
     * 获取指定Channel
     * @param key
     * @return
     */
    public static Channel get(String key) {
        return userChannelMap.get(key);
    }

    /**
     * 添加指定Channel
     * @param key
     */
    public static void put(String key, Channel channel) {
        log.debug("添加{}的channel管理", key);
        channelGroup.add(channel);
        userChannelMap.put(key, channel);
    }

    /**
     * 删除并同步关闭指定Channel
     * @param key
     */
    public static void removeAndClose(String key) {
        log.debug("删除并关闭{}的channel", key);
        Channel channel = userChannelMap.remove(key);
        if (null != channel) {
            channelGroup.remove(channel);
            if (channel.isOpen()) {
                channel.close();
            }
        }
    }

    /**
     * 删除并同步关闭指定Channel
     * @param channel
     */
    public static void removeAndClose(Channel channel) {
        if(null == channel) {
            return;
        }
        String token = getToken(channel);
        removeAndClose(token);
        if (channel.isOpen()) {
            channel.close();
        }
    }

    /**
     * 从channel中获取token
     * @param channel
     * @return
     */
    public static String getToken(Channel channel) {
        AttributeKey<String> key = AttributeKey.valueOf("token");
        return channel.attr(key).get();
    }


}
